package com.zzyl.nursing.service.impl;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zzyl.common.constant.CacheConstants;
import com.zzyl.common.core.page.TableDataInfo;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.domain.Device;
import com.zzyl.nursing.dto.DeviceDataPageReqDto;
import com.zzyl.nursing.mapper.DeviceMapper;
import com.zzyl.nursing.task.Content;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.mapper.DeviceDataMapper;
import com.zzyl.nursing.domain.DeviceData;
import com.zzyl.nursing.service.IDeviceDataService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 设备数据Service业务层处理
 * 
 * @author laolin
 * @date 2025-01-06
 */
@Service
@Slf4j
public class DeviceDataServiceImpl extends ServiceImpl<DeviceDataMapper, DeviceData> implements IDeviceDataService
{
    @Autowired
    private DeviceDataMapper deviceDataMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 查询设备数据
     * 
     * @param id 设备数据主键
     * @return 设备数据
     */
    @Override
    public DeviceData selectDeviceDataById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询设备数据列表
     *
     * @param dto 设备数据
     * @return 设备数据
     */
    @Override
    public TableDataInfo<DeviceData> selectDeviceDataList(DeviceDataPageReqDto dto)
    {
        //1. 设置分页参数
        Page<DeviceData> pageInfo = Page.of(dto.getPageNum(), dto.getPageSize());
        //2. 构建查询条件
        lambdaQuery().like(StrUtil.isNotEmpty(dto.getDeviceName()),DeviceData::getDeviceName, dto.getDeviceName())
                .eq(StrUtil.isNotEmpty(dto.getFunctionId()), DeviceData::getFunctionId, dto.getFunctionId())
                .ge(null != dto.getStartTime(), DeviceData::getAlarmTime, dto.getStartTime())
                .le(null != dto.getEndTime(), DeviceData::getAlarmTime, dto.getEndTime())
                .page(pageInfo);
        TableDataInfo<DeviceData> tableDataInfo = new TableDataInfo<>();
        tableDataInfo.setCode(200);
        tableDataInfo.setRows(pageInfo.getRecords());
        tableDataInfo.setTotal(pageInfo.getTotal());
        return tableDataInfo;
    }

    /**
     * 新增设备数据
     * 
     * @param deviceData 设备数据
     * @return 结果
     */
    @Override
    public int insertDeviceData(DeviceData deviceData)
    {
        return save(deviceData) ? 1 : 0;
    }

    /**
     * 修改设备数据
     * 
     * @param deviceData 设备数据
     * @return 结果
     */
    @Override
    public int updateDeviceData(DeviceData deviceData)
    {
        return updateById(deviceData) ? 1 : 0;
    }

    /**
     * 批量删除设备数据
     * 
     * @param ids 需要删除的设备数据主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除设备数据信息
     * 
     * @param id 设备数据主键
     * @return 结果
     */
    @Override
    public int deleteDeviceDataById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }


    /**
     * 批量保存设备上报的数据
     *
     * @param content
     */
    @Transactional
    @Override
    public void batchInsertDeviceData(Content content) {
        //1.通过iot_id查询设备信息
        String iotId = content.getIotId();
        Device device = deviceMapper.selectOne(new LambdaQueryWrapper<Device>().eq(Device::getIotId, iotId));
        //2.设备不存在则不处理return
        if(null == device){
            log.info("设备不存在: {}", iotId);
            return;
        }
        //3. 设备存在
        // 数据转成，每个物模型属性就一条记录，设备上报的数据有多个物模型属性就有多条记录
        Map<String, Content.Item> items = content.getItems();
        List<DeviceData> deviceDataList = items.entrySet().stream().map(entry -> {
            //key=>BodyTemp, value:Item{value:,time:}
            String functionId = entry.getKey();
            Content.Item item = entry.getValue();
            //转换data数据
            DeviceData deviceData = BeanUtil.toBean(device, DeviceData.class);
            deviceData.setAccessLocation(device.getRemark());
            deviceData.setDataValue(String.valueOf(item.getValue()));
            deviceData.setAlarmTime(LocalDateTimeUtil.of(item.getTime()));
            deviceData.setFunctionId(functionId);
            // id属性值是从device对象复制过来的，device对象从数据库查询出来的。4条记录主键是同一个id，导致插入报错
            // device_data主键自增
            deviceData.setId(null);
            return deviceData;
        }).collect(Collectors.toList());
        if(CollUtil.isNotEmpty(deviceDataList)){
            saveBatch(deviceDataList);
        }
        // 存入到redis  key：hash数据类型（大key，小key,  value）iot:device_last_data   iot_id
        stringRedisTemplate.opsForHash().put(CacheConstants.IOT_DEVICE_LAST_DATA, content.getIotId(), JSONUtil.toJsonStr(deviceDataList));
    }

}

